package com.itany.shop.util;

import com.itany.shop.exception.DataAccessException;
import org.apache.commons.dbcp.BasicDataSourceFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

/**
 * @author 石小俊
 * @date 2023年07月05日 15:51
 * JDBC工具类
 * 使用这个类加载类加载路径下的dataSource.properties文件
 * 读取文件中的信息配置一个数据库连接池
 * 此处使用的commons-dbcp
 */
public class JDBCUtil {

    private static DataSource ds;
    private static ThreadLocal<Connection> local;

    static{
        try {
            local = new ThreadLocal<>();
            Properties properties = new Properties();
            properties.load(JDBCUtil.class.getClassLoader().getResourceAsStream("dataSource.properties"));
            ds = BasicDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ExceptionInInitializerError("JDBCUtil初始化失败");
        }
    }

    /**
     * 获取连接
     * 使用数据库连接池的方式获取一个连接,该连接是线程单例的
     * @return
     */
    public static Connection getConnection(){
        // 从连接池中获取连接
        Connection conn = local.get();

        try {
            // 如果连接池中没有连接
            if(conn == null){
                // 需要获取一个新的连接
                conn = ds.getConnection();
                // 并将该连接放入到连接池中
                local.set(conn);
            }
        } catch (SQLException e) {
            e.printStackTrace();
            throw new DataAccessException("获取连接失败");
        }
        // 返回获取到的连接
        return conn;
    }

    /**
     * 释放持久层连接
     * @param conn
     * @param ps
     * @param rs
     */
    public static void close(Connection conn, PreparedStatement ps, ResultSet rs){
        try {
            if(conn != null){
                conn.close();
            }
        } catch (SQLException e) {
            throw new DataAccessException("释放连接出错");
        }
        try {
            if(ps != null){
                ps.close();
            }
        } catch (SQLException e) {
            throw new DataAccessException("释放状态集出错");
        }
        try {
            if(rs != null){
                rs.close();
            }
        } catch (SQLException e) {
            throw new DataAccessException("释放结果集出错");
        }
    }

    /**
     * 释放业务层连接
     */
    public static void close(){
        // 取出连接池中的连接
        Connection conn = local.get();
        // 如果没有取到连接,说明连接已经被释放了,则不需要进行处理
        // 如果取到连接了,则需要对连接进行释放
        try {
            if(conn != null){
                // 释放连接
                conn.close();
            }
            // 将连接从连接池中移除
            local.remove();
        } catch (SQLException e) {
            throw new DataAccessException("释放连接出错");
        }
    }
}
